﻿using System;
using System.Reflection;
using System.Collections;
using System.Configuration;
using System.Collections.Generic;

using LeanEngine.Entity;
using LeanEngine.Collections;

namespace LeanEngine.Data
{
    /// <summary>
    /// Represents create, read, update and delete sql commands.
    /// </summary>
    public sealed class CrudCommand : IDisposable
    {
        #region PropertyInfo Members

        private ICrudCommand Command { get; set; }
        private ISqlTextBuilder SqlTextBuilder { get; set; }

        #endregion

        #region Constructor Members

        /// <summary>
        /// Initialize a new instance of the LeanEngine.Data.Common.DataCommand class
        /// </summary>
        public CrudCommand()
        {
            this.Command = DataProvider.NewCrudCommand();
            this.SqlTextBuilder = DataProvider.NewSqlTextBuilder();
        }

        #endregion

        #region Method Members

        /// <summary>
        /// Execute an insert sql command against the database.
        /// </summary>
        /// <exception cref="System.Data.DataException"></exception>
        /// <param name="value">The transfer object's to be saved on database</param>
        public void ExecuteInsert(PlainEntity value)
        {
            this.Command.ExecuteInsert(value);
        }

        /// <summary>
        /// Execute an insert command for all relation value values into the specified table.
        /// </summary>
        /// <exception cref="ArgumentNullException"></exception>
        /// <param name="table">The relation table name.</param>
        /// <param name="value">The first relation transfer object instance.</param>
        /// <param name="relationList">The list of tranfer object values of the second relation.</param>
        public void ExecuteInsertRelation(string table, PlainEntity value, IList relationList)
        {
            this.Command.ExecuteInsertRelation(table, value, relationList);
        }

        /// <summary>
        /// Execute an update sql command against the database.
        /// </summary>
        /// <exception cref="System.Data.DataException"></exception>
        /// <param name="value">The transfer object's to be saved on database</param>
        public void ExecuteUpdate(PlainEntity value)
        {
            this.Command.ExecuteUpdate(value);
        }

        /// <summary>
        /// Execute a delete sql command against the database.
        /// </summary>
        /// <exception cref="System.Data.DataException"></exception>
        /// <param name="value">The transfer object will be deleted.</param>
        public void ExecuteDelete(PlainEntity value)
        {
            this.Command.ExecuteDelete(value);
        }

        /// <summary>
        /// Execute a delete sql command to delete all relation values of the specified table.
        /// </summary>
        /// <exception cref="ArgumentNullException"></exception>
        /// <param name="table">The relation table name.</param>
        /// <param name="value">The first relation transfer object instance.</param>
        /// <param name="relationList">The list of tranfer object values of the second relation.</param>
        public void ExecuteDeleteRelation(string table, PlainEntity value, IList relationList)
        {
            this.Command.ExecuteDeleteRelation(table, value, relationList);
        }

        /// <summary>
        /// Execute a count sql command against the database.
        /// </summary>
        /// <exception cref="System.Data.DataException"></exception>
        /// <param name="entityType">The type of the transfer object.</param>
        public long ExecuteCount(Type entityType)
        {
            return this.Command.ExecuteCount(entityType);
        }

        /// <summary>
        /// Execute a select command againt the database and returns a paged list of data.
        /// </summary>
        /// <typeparam name="T">Transfer object type</typeparam>
        /// <param name="pageIndex">Page index to be searched for</param>
        /// <param name="pageSize">Page size to be returned</param>
        /// <returns>A page list class with its itens returned by the command</returns>
        public PagedList<T> ExecuteReader<T>(int pageIndex, int pageSize)
            where T : PlainEntity, new()
        {
            return this.Command.ExecuteReader<T>(pageIndex, pageSize);
        }

        /// <summary>
        /// Execute a select command to retrieve all values of a transfer object and fill it with.
        /// </summary>
        /// <exception cref="System.Data.DataException"></exception>
        /// <param name="value">The transfer object will be readed.</param>
        public PlainEntity ExecuteReader(PlainEntity value)
        {
            return this.Command.ExecuteReader(value);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Command = null;
        }

        #endregion
    }
}
